﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Book_of_Shadow_Script
{

    //文件修改
    class Modify
    {
        public int addr { get; set; }
        int len;
        private Byte[] buffer;
        public int length 
        {
            get
            {
                return buffer.Length;
            }
        }
        public Byte[] bytes
        {
            get
            {
                return buffer;
            }
        }

        //string
        public Modify(int addr, int maxlen, string str, Encoding en)
        {
            this.addr = addr;
            len = en.GetByteCount(str);
            if (len > maxlen) throw new ByteLengthExceed();
            buffer = en.GetBytes(str);
        }
        public Modify(int addr, int maxlen, string str, Encoding en, out int newaddr)
            :this(addr,maxlen,str,en)
        {
            newaddr = addr + len;
        }

        //integer
        public Modify(int addr, int len, int integer)
        {
            this.addr = addr;
            this.len = len;
            buffer = new Byte[len];
            for (int i = 0; i < len; i++)
            {
                buffer[i] = (Byte)(integer & 0xFF);
                integer >>= 8;
            }
            if (integer > 0) throw new ByteLengthExceed();
        }
    }
    //bin游戏文本
    class SceneFileByte
    {
        private String fName;
        private FileStream fs;
        Encoding en;
        public SceneFileByte(String fName, CodePage cdp)
        {
            this.fName = fName;
            fs = File.Open(fName, FileMode.Open, FileAccess.Write);
            en = new CustomEncoding(cdp.CharToByte(),cdp.ByteToChar());
        }

        public SceneFileByte(String fName, CodePageFixed cpf)
        {
            this.fName = fName;
            fs = File.Open(fName, FileMode.Open, FileAccess.Write);
            en = new CustomEncoding(cpf.ToByte, cpf.ToChar);
        }
        public SceneFileByte(String fName, Encoding ens)
        {
            this.fName = fName;
            fs = File.Open(fName, FileMode.Open, FileAccess.Write);
            en = ens;
        }
        ~SceneFileByte()
        {
            fs.Close();
        }
        public void Close()
        {
            fs.Close();
        }
        public void Import(SceneFile sf)
        {
            while (!sf.FileEnd())
            {
                Modify[] mods = sf.GetNextModifys(en);
                if (mods == null) continue;
                foreach (Modify mo in mods)
                {
                    fs.Seek(mo.addr, SeekOrigin.Begin);
                    fs.Write(mo.bytes, 0, mo.length);
                }
            }
        }
    }
    //导出文本
    abstract class SceneFile
    {
        private String fName;
        protected StreamReader sr;
        public SceneFile(string fName)
        {
            sr = new StreamReader(fName);
            this.fName = fName;
        }
        ~SceneFile()
        {
            sr.Close();
        }

        public bool FileEnd()
        {
            return sr.EndOfStream;
        }
        public abstract Modify[] GetNextModifys(Encoding en);
    }
    //影之书文本
    class SceneFile_Book_of_Shadow : SceneFile
    {
        
        int nowaddr=-1;
        public SceneFile_Book_of_Shadow(string fName)
            :base(fName)
        {
        }
        public override Modify[] GetNextModifys(Encoding en)
        {
            String[] fullstr=new String[64];
            String rs,str;
            int i = 0;
            while (true)
            {
                rs = sr.ReadLine().Trim();
                if (rs != string.Empty)
                {
                    fullstr[i] = rs;
                    i++;
                }
                else
                {
                    if (i > 6) break;
                }
                if (sr.EndOfStream) break;
            }

            TextFormat_Book_of_Shadow tb = new TextFormat_Book_of_Shadow(fullstr);

            Modify[] mods = new Modify[tb.Count*2];
            int j=0;
            if (tb.ID==1) this.nowaddr=tb.FirstAddr;
            if (tb.Type == 0x1B)
            {
                int tba = tb.Address + 8;
                for (i = 0; i < tb.Count; i++)
                {
                    int tmp = nowaddr;
                    mods[j] = new Modify(tba, 4, nowaddr);
                    j++;
                    str = tb.Text(i);
                    mods[j] = new Modify(nowaddr, 0xFF, str, en, out tmp);
                    nowaddr = tmp;
                    tba += 10;
                    j++;
                }
            }
            else
            {
                int tmp = nowaddr;
                mods[j] = new Modify(tb.Address + 6, 4, nowaddr);
                j++;
                str = tb.Text(0);
                mods[j] = new Modify(nowaddr, 0xFF, str, en, out tmp);
                nowaddr = tmp;
                j++;
            }
            return mods;
        }
    }
    //WQSG文本
    class SceneFile_WQSG : SceneFile
    {
        public SceneFile_WQSG(string fName)
            : base(fName)
        {
        }
        public override Modify[] GetNextModifys(Encoding en)
        {
            Modify[] mods=new Modify[1];
            String fullstr=sr.ReadLine();
            fullstr = fullstr.Trim();
            while (fullstr!=null && fullstr.Length == 0)
            {
                fullstr = sr.ReadLine();
                if (fullstr != null) fullstr = fullstr.Trim();
            }
            if (fullstr == null) return null;
            TextFormat_WQSG tb = new TextFormat_WQSG(fullstr);
            try
            {
                mods[0] = new Modify(tb.Address, tb.Length, tb.String, en);
                return mods;
            }
            catch (ByteLengthExceed e)
            {
                System.Windows.Forms.MessageBox.Show(fullstr + " 超字节");
                return null;
            }
        }
    }
}
